Recently I've encountered a modularity issue in my code, I had a function like the following
sub _is_event_pass { return ($self->_event->is_ok() || $self->_event->is_skip() || $self->_event->is_todo() ); }
As you can see all I'm doing is calling methods on the _event. The right thing to do would have been to move it as method to the class of the _event() that will then use the object's instance itself. Now the problem is that the _event() field can be any of the TAP::Result:: hierarchy of classes
And it wouldn't be a good idea to sub-class and re-bless all of them.
So what to do?
What I eventually did is create an EventWrapper class, that has a field which is the actual object. Then I'm delegating all the methods of the TAP::Result classes that I use to that field. I.e:
sub is_ok { my $self = shift; return $self->_tp_result()->is_ok(); } sub is_todo { my $self = shift; return $self->_tp_result()->is_todo(); }
(only I'm auto-generating these methods of-course).
And then I defined the is_pass function there like this:
sub is_pass { my $self = shift; return ($self->is_ok() || $self->is_todo() || $self->is_skip()); }
Which works because these methods are delegated.
So ::EventWrapper behaves like TAP::Result ("is-a") while actually only containing it ("has-a"). It's a useful technique.
Of course, I made a good use of the fact that Perl is dynamically-typed and evaluates methods at run-time. If I wanted to do the same in strongly-typed OO languages, then I would have needed to figure out a way to delegate to all the methods of the various different classes in the hiearachy. Perhaps using run-time classes.